package com.zhulong.saas.cloud.gateway.security;

import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.ReactiveAuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.server.authorization.AuthorizationContext;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.function.Predicate;

public class AndReactiveAuthorizationManager implements ReactiveAuthorizationManager<AuthorizationContext> {

    private List<ReactiveAuthorizationManager<AuthorizationContext>> authorizationManagers;

    public AndReactiveAuthorizationManager(List<ReactiveAuthorizationManager<AuthorizationContext>> authorizationManagers) {
        this.authorizationManagers = authorizationManagers;
    }

    @Override
    public Mono<AuthorizationDecision> check(Mono<Authentication> authentication, AuthorizationContext context) {
        return Flux.fromIterable(authorizationManagers)
                .flatMap(a -> a.check(authentication, context))
                .any(((Predicate<? super AuthorizationDecision>) (AuthorizationDecision::isGranted)).negate())
                .map(b -> new AuthorizationDecision(!b))
                .switchIfEmpty(Mono.just(new AuthorizationDecision(false)));
    }
}
